package com.zero.guava.samples.CollectionsDemo;

import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Doubles;

import java.util.Comparator;
import java.util.List;

/**
 * Guava提供的Ordering排序比较器就旨在解决集合排序的问题
 * natural()：使用自然排序。
 * from(Comparator comparator)：返回一个传入comparator实例的Ordering。
 * explicit(List valuesInOrder)：返回一个Ordering，比较对象根据他们出现在给定的列表的顺序。
 * explicit( T leastValue, T... remainingValuesInOrder)：返回一个Ordering，比较对象根据它们的传入的顺序。
 * allEqual()：返回一个Ordering，所有值的排序地位都是平等的，表明无排序。
 * usingToString()：根据toString返回的字符串按照字典顺序排序。
 * arbitrary()：返回所有对象的任意顺序， 即compare(a, b) == 0 就是 a == b (identity equality)。 本身的排序是没有任何含义， 但是在VM的生命周期是一个常量。
 * reverse()：返回与当前Ordering相反的排序。
 * nullsFirst()：根据Ordering排序，null值放在最前面。
 * nullsLast()：根据Ordering排序，null值放在最后面。
 * onResultOf(Function<F, ? extends T> function)：将传入function应用到每个元素上面，再通过Ordering进行排序。
 * compound( Comparator<? super U> secondaryComparator)：返回一个Ordering，传入比较器作为第二排序元素。
 * compound( Iterable<? extends Comparator<? super T>> comparators)：返回一个Ordering，会根据传入比较器集合一次比较，直到找到一个非零的结果。
 * lexicographical()：返回一个新的Ordering，通过相应的元素两两迭代，直到找到一个非零的结果。
 * min(Iterator iterator)：根据Ordering返回传入参数的最小值。
 * min(Iterable iterable)：根据Ordering返回传入参数的最小值。
 * min(@Nullable E a, @Nullable E b)：根据Ordering返回传入参数的最小值。
 * min( @Nullable E a, @Nullable E b, @Nullable E c, E... rest)：根据Ordering返回传入参数的最小值。
 * max(Iterator iterator)：根据Ordering返回传入参数的最大值。
 * max(Iterable iterable)：根据Ordering返回传入参数的最大值。
 * max(@Nullable E a, @Nullable E b)：根据Ordering返回传入参数的最大值。
 * max( @Nullable E a, @Nullable E b, @Nullable E c, E... rest)：根据Ordering返回传入参数的最大值。
 * leastOf(Iterable iterable, int k)：根据Ordering对传入iterable由小到大排序，返回前K位的集合。
 * leastOf(Iterator elements, int k)：根据Ordering对传入iterator由小到大排序，返回前K位的集合。
 * greatestOf(Iterable iterable, int k)：根据Ordering对传入iterable由大到小排序，返回前K位的集合。
 * greatestOf(Iterator iterator, int k)：根据Ordering对传入iterator由大到小排序，返回前K位的集合。
 * sortedCopy(Iterable elements)：返回一个可变的集合，包含根据Ordering对传入元素排序后的所有元素。
 * immutableSortedCopy( Iterable elements)：返回一个不可变的集合，包含根据Ordering对传入元素排序后的所有元素。
 * isOrdered(Iterable<? extends T> iterable)：根据Ordering对传入iterable元素迭代，如果下一个元素大于或等于上一个元素，返回true。
 * isStrictlyOrdered(Iterable<? extends T> iterable)：根据Ordering对传入iterable元素迭代，如果下一个元素严格大于上一个元素，返回true。
 * binarySearch(List<? extends T> sortedList, @Nullable T key)：传入Ordering排序过的List集合和需要查询的key，进行二分查找。
 */
public class OrderingTest {

    public static void main(String[] args) {
        testOrdering();
    }


    public static void testOrdering() {

        Double first = 0.1;
        Double[] second = {0.2, 0.3};
        List<Double> numbers = Lists.asList(first, second);
        //排序比较器：根据原始的大小排序
        Ordering<Double> peopleOrdering = new Ordering<Double>() {
            @Override
            public int compare(Double left, Double right) {
                return Doubles.compare(left, right);
            }
        };

        //自定义比较器：根据1除以原始值后得到的值的大小排序
        Comparator<Double> comparator = new Comparator<Double>() {
            @Override
            public int compare(Double o1, Double o2) {
                return Doubles.compare(1 / o1, 1 / o2);
            }
        };

        //sortedCopy:对传入的集合进行Ordering排序比较
        peopleOrdering.sortedCopy(numbers); //[0.1, 0.2, 0.3]
        //reverse:对Ordering进行反向排序
        peopleOrdering.reverse().sortedCopy(numbers);//[0.3, 0.2, 0.1]

        //from:根据传入comparator作为排序的比较器
        peopleOrdering.from(comparator).sortedCopy(numbers); //[0.3, 0.2, 0.1]
        peopleOrdering.from(comparator).reverse().sortedCopy(numbers);//[0.1, 0.2, 0.3]

        //isOrdered:根据Ordering对传入iterable元素迭代，如果下一个元素大于或等于上一个元素，返回true
        peopleOrdering.isOrdered(numbers);//true
        peopleOrdering.from(comparator).isOrdered(numbers);//false

        //explicit:根据传入对象的顺序排序
        peopleOrdering.reverse().explicit(numbers).sortedCopy(numbers);//[0.1, 0.2, 0.3]

        //arbitrary:返回所有对象任意顺序
        peopleOrdering.arbitrary().sortedCopy(numbers);

        //compound: 返回一个Ordering，comparator作为第二排序元素
        peopleOrdering.reverse().compound(comparator).sortedCopy(numbers); //[0.3, 0.2, 0.1]
    }

}
